package com.example.smartagrisys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartagrisys.common.ResultCode;
import com.example.smartagrisys.dto.LandCropRecordDTO;
import com.example.smartagrisys.dto.LandCropRecordQueryDTO;
import com.example.smartagrisys.entity.Land;
import com.example.smartagrisys.entity.LandCropRecord;
import com.example.smartagrisys.entity.User;
import com.example.smartagrisys.exception.BusinessException;
import com.example.smartagrisys.mapper.LandCropRecordMapper;
import com.example.smartagrisys.mapper.LandMapper;
import com.example.smartagrisys.service.LandCropRecordService;
import com.example.smartagrisys.service.LandService;
import com.example.smartagrisys.service.UserService;
import com.example.smartagrisys.vo.LandCropRecordVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 土地作物记录服务实现
 */
@Slf4j
@Service
public class LandCropRecordServiceImpl extends ServiceImpl<LandCropRecordMapper, LandCropRecord> implements LandCropRecordService {

    @Resource
    private LandMapper landMapper;

    @Resource
    private UserService userService;

    @Resource
    private LandService landService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long add(LandCropRecordDTO dto, Long farmerId) {
        // 检查用户是否为农户角色
        checkFarmerUser(farmerId);
        
        // 检查土地是否存在
        Land land = checkLand(dto.getLandId(), farmerId);

        // 创建记录实体
        LandCropRecord record = new LandCropRecord();
        BeanUtils.copyProperties(dto, record);
        record.setFarmerId(farmerId);
        record.setStatus(0); // 默认状态：种植中
        record.setActualYield(null); // 初始实际产量为空

        // 计算预期产量/亩
        if (dto.getExpectedYield() != null && dto.getPlantingArea() != null 
                && dto.getPlantingArea().compareTo(BigDecimal.ZERO) > 0) {
            record.setYieldPerUnit(dto.getExpectedYield().divide(dto.getPlantingArea(), 2, BigDecimal.ROUND_HALF_UP));
        }

        // 保存记录
        save(record);

        // 更新土地状态为已种植
        land.setStatus(1); // 已种植
        land.setCurrentCrop(dto.getCropName());
        land.setPlantingDate(dto.getPlantingDate());
        landMapper.updateById(land);

        log.info("农户 {} 添加土地 {} 作物记录：{}", farmerId, dto.getLandId(), record.getId());
        return record.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(LandCropRecordDTO dto, Long farmerId) {
        // 检查用户是否为农户角色
        checkFarmerUser(farmerId);
        
        // 检查记录是否存在
        LandCropRecord record = getById(dto.getId());
        if (record == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "作物记录不存在");
        }

        // 检查土地是否存在
        Land land = checkLand(record.getLandId(), farmerId);

        // 检查记录状态
        if (record.getStatus() == 1) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "作物已收获，无法修改");
        }

        // 更新记录
        BeanUtils.copyProperties(dto, record);

        // 计算预期产量/亩
        if (dto.getExpectedYield() != null && dto.getPlantingArea() != null 
                && dto.getPlantingArea().compareTo(BigDecimal.ZERO) > 0) {
            record.setYieldPerUnit(dto.getExpectedYield().divide(dto.getPlantingArea(), 2, BigDecimal.ROUND_HALF_UP));
        }

        // 更新土地信息
        land.setCurrentCrop(dto.getCropName());
        land.setPlantingDate(dto.getPlantingDate());
        landMapper.updateById(land);

        log.info("农户 {} 更新作物记录：{}", farmerId, record.getId());
        return updateById(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long id, Long farmerId) {
        // 检查用户是否为农户角色
        checkFarmerUser(farmerId);
        
        // 检查记录是否存在
        LandCropRecord record = getById(id);
        if (record == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "作物记录不存在");
        }

        // 检查土地是否存在
        Land land = landMapper.selectById(record.getLandId());
        if (land != null) {
            // 如果是正在种植的记录，则更新土地状态为闲置
            if (record.getStatus() == 0 && land.getStatus() == 1) {
                land.setStatus(0); // 闲置
                land.setCurrentCrop(null);
                land.setPlantingDate(null);
                landMapper.updateById(land);
            }
        }

        log.info("农户 {} 删除作物记录：{}", farmerId, id);
        return removeById(id);
    }

    @Override
    public LandCropRecordVO getDetail(Long id) {
        // 获取记录信息
        LandCropRecord record = getById(id);
        if (record == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "作物记录不存在");
        }

        return convertToVO(record);
    }

    @Override
    public Page<LandCropRecordVO> page(LandCropRecordQueryDTO queryDTO) {
        // 创建分页对象
        Page<LandCropRecord> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        // 构建查询条件
        LambdaQueryWrapper<LandCropRecord> wrapper = new LambdaQueryWrapper<>();

        // 按土地ID查询
        if (queryDTO.getLandId() != null) {
            wrapper.eq(LandCropRecord::getLandId, queryDTO.getLandId());
        }

        // 按农户ID查询
        if (queryDTO.getFarmerId() != null) {
            wrapper.eq(LandCropRecord::getFarmerId, queryDTO.getFarmerId());
        }

        // 按作物名称模糊查询
        if (StringUtils.hasText(queryDTO.getCropName())) {
            wrapper.like(LandCropRecord::getCropName, queryDTO.getCropName());
        }

        // 按作物品种模糊查询
        if (StringUtils.hasText(queryDTO.getCropVariety())) {
            wrapper.like(LandCropRecord::getCropVariety, queryDTO.getCropVariety());
        }

        // 按状态查询
        if (queryDTO.getStatus() != null) {
            wrapper.eq(LandCropRecord::getStatus, queryDTO.getStatus());
        }

        // 按种植日期范围查询
        if (queryDTO.getPlantingDateStart() != null) {
            wrapper.ge(LandCropRecord::getPlantingDate, queryDTO.getPlantingDateStart());
        }
        if (queryDTO.getPlantingDateEnd() != null) {
            wrapper.le(LandCropRecord::getPlantingDate, queryDTO.getPlantingDateEnd());
        }

        // 按收获日期范围查询
        if (queryDTO.getHarvestDateStart() != null) {
            wrapper.ge(LandCropRecord::getHarvestDate, queryDTO.getHarvestDateStart());
        }
        if (queryDTO.getHarvestDateEnd() != null) {
            wrapper.le(LandCropRecord::getHarvestDate, queryDTO.getHarvestDateEnd());
        }

        // 按创建时间降序
        wrapper.orderByDesc(LandCropRecord::getCreateTime);

        // 执行分页查询
        page = page(page, wrapper);

        // 转换结果
        Page<LandCropRecordVO> resultPage = new Page<>();
        BeanUtils.copyProperties(page, resultPage, "records");

        // 获取所有ID
        List<Long> landIds = page.getRecords().stream()
                .map(LandCropRecord::getLandId)
                .distinct()
                .collect(Collectors.toList());

        List<Long> farmerIds = page.getRecords().stream()
                .map(LandCropRecord::getFarmerId)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询信息
        List<Land> lands = landIds.isEmpty() ? Collections.emptyList() :
                landMapper.selectBatchIds(landIds);

        List<User> farmers = farmerIds.isEmpty() ? Collections.emptyList() :
                userService.listByIds(farmerIds);

        // 转换为map，方便查找
        Map<Long, Land> landMap = new HashMap<>();
        lands.forEach(land -> landMap.put(land.getId(), land));

        Map<Long, User> farmerMap = new HashMap<>();
        farmers.forEach(user -> farmerMap.put(user.getId(), user));

        // 转换为VO列表
        List<LandCropRecordVO> records = page.getRecords().stream()
                .map(record -> {
                    LandCropRecordVO vo = convertToVO(record);

                    // 设置土地名称
                    Land land = landMap.get(record.getLandId());
                    if (land != null) {
                        vo.setLandName(land.getName());
                    }

                    // 设置农户姓名
                    User farmer = farmerMap.get(record.getFarmerId());
                    if (farmer != null) {
                        vo.setFarmerName(farmer.getNickname());
                    }

                    return vo;
                })
                .collect(Collectors.toList());

        resultPage.setRecords(records);
        return resultPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(Long id, Integer status, Long farmerId) {
        // 检查用户是否为农户角色
        checkFarmerUser(farmerId);
        
        // 检查记录是否存在
        LandCropRecord record = getById(id);
        if (record == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "作物记录不存在");
        }

        // 检查状态是否有效
        if (status < 0 || status > 2) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "无效的记录状态");
        }

        // 更新状态
        record.setStatus(status);

        // 如果是收获状态，设置收获日期
        if (status == 1 && record.getHarvestDate() == null) {
            record.setHarvestDate(LocalDateTime.now());
        }

        // 如果是已收获，更新土地状态
        if (status == 1) {
            // 检查土地是否存在
            Land land = landMapper.selectById(record.getLandId());
            if (land != null) {
                land.setStatus(2); // 已收获
                landMapper.updateById(land);
            }
        }

        log.info("农户 {} 更新作物记录 {} 状态为：{}", farmerId, id, status);
        return updateById(record);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean recordHarvest(Long id, BigDecimal actualYield, Long farmerId) {
        // 检查用户是否为农户角色
        checkFarmerUser(farmerId);
        
        // 检查记录是否存在
        LandCropRecord record = getById(id);
        if (record == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "作物记录不存在");
        }

        // 检查记录状态
        if (record.getStatus() != 0) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "作物当前状态不允许记录收获");
        }

        // 更新记录
        record.setStatus(1); // 已收获
        record.setActualYield(actualYield);
        record.setHarvestDate(LocalDateTime.now());

        // 计算实际产量/亩
        if (actualYield != null && record.getPlantingArea() != null 
                && record.getPlantingArea().compareTo(BigDecimal.ZERO) > 0) {
            record.setYieldPerUnit(actualYield.divide(record.getPlantingArea(), 2, BigDecimal.ROUND_HALF_UP));
        }

        // 更新土地状态
        Land land = landMapper.selectById(record.getLandId());
        if (land != null) {
            land.setStatus(2); // 已收获
            landMapper.updateById(land);
        }

        log.info("农户 {} 记录作物收获：{}，产量：{}", farmerId, id, actualYield);
        return updateById(record);
    }

    @Override
    public Page<LandCropRecordVO> getLandCropRecords(Long landId, Integer pageNum, Integer pageSize) {
        // 检查土地是否存在
        Land land = landMapper.selectById(landId);
        if (land == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "土地不存在");
        }

        // 创建查询对象
        LandCropRecordQueryDTO queryDTO = new LandCropRecordQueryDTO();
        queryDTO.setLandId(landId);
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);

        return page(queryDTO);
    }

    @Override
    public Page<LandCropRecordVO> getFarmerCropRecords(Long farmerId, Integer pageNum, Integer pageSize) {
        // 检查用户是否为农户角色
        User user = checkFarmerUser(farmerId);

        // 创建查询对象
        LandCropRecordQueryDTO queryDTO = new LandCropRecordQueryDTO();
        queryDTO.setFarmerId(farmerId);
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);

        return page(queryDTO);
    }

    @Override
    public String getStatusName(Integer status) {
        if (status == null) {
            return "未知";
        }

        switch (status) {
            case 0: return "种植中";
            case 1: return "已收获";
            case 2: return "已作废";
            default: return "未知";
        }
    }

    /**
     * 检查用户是否为农户角色
     */
    private User checkFarmerUser(Long userId) {
        // 查询用户信息
        User user = userService.getById(userId);
        if (user == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "用户不存在");
        }
        
        // 检查用户角色是否为农户
        if (!"farmer".equals(user.getRole())) {
            throw new BusinessException(ResultCode.FORBIDDEN, "只有农户才能管理土地作物记录");
        }
        
        return user;
    }

    /**
     * 检查土地是否存在且属于指定农户
     */
    private Land checkLand(Long landId, Long farmerId) {
        Land land = landMapper.selectById(landId);
        if (land == null) {
            throw new BusinessException(ResultCode.BAD_REQUEST, "土地不存在");
        }

        // 检查是否为土地所有者
        if (!land.getFarmerId().equals(farmerId)) {
            throw new BusinessException(ResultCode.FORBIDDEN, "您无权操作此土地");
        }

        return land;
    }

    /**
     * 将实体转换为VO
     */
    private LandCropRecordVO convertToVO(LandCropRecord record) {
        LandCropRecordVO vo = new LandCropRecordVO();
        BeanUtils.copyProperties(record, vo);

        // 设置状态名称
        vo.setStatusName(getStatusName(record.getStatus()));

        // 尝试获取土地和农户信息
        Land land = landMapper.selectById(record.getLandId());
        if (land != null) {
            vo.setLandName(land.getName());
        }

        User farmer = userService.getById(record.getFarmerId());
        if (farmer != null) {
            vo.setFarmerName(farmer.getNickname());
        }

        return vo;
    }
} 